import datetime
import json
import os
import pickle
import time
import traceback

import math
from flask import current_app, request
from flask_restful import reqparse

from shop.conf import GOODS_INDEX_PATH, mingan_words, VERSION_NUM, SHOP_API_URL
from shop.handler.v1_handler import BrowseHandler, RushBugHandler
from shop.model import get_pickle_file_path, set_pickle_file_path, db, get_phone_code, save_user_token, \
    check_user_token, pool
from shop.model.feedback import Feedback
from shop.model.searchwords import save_one_searchwords
from shop.model.user import User, get_user_by_phone
from shop.model.user_browse import UserBrowse
from shop.util.goods_operation import get_all_kind_goods, util_search_goods, util_get_yhq, \
    get_recommend_goods
from shop.util.miaoyouquan_operation import MiaoHandler
from shop.util.mylogger import MyLogger, Alogger
from shop.util.send_message import send_message
from shop.util.server_jiang import send_feedback_to_wexin
from shop.util.string_operation import get_md5_str
from shop.views.inherit_class import My_resource


class Goods(My_resource):

    def __init__(self):
        self.parser = reqparse.RequestParser()
        self.parser.add_argument("page")
        self.parser.add_argument("kind")
        self.parser.add_argument('words')
        self.parser.add_argument('order')
        self.parser.add_argument("timestamp")
        self.parser.add_argument("hash_string")

    def get(self):
        args = self.parser.parse_args()
        args_page = args.get('page')
        args_kind = args.get("kind")
        time_stamp = args.get("timestamp")
        hash_string = args.get("hash_string")
        # 验证hash_string
        res = self.check_hash(time_stamp, hash_string)
        if not res:
            return self.hasherror()
        # 验证ip黑名单
        is_black_ip = self.check_black_ip()
        if is_black_ip:
            return self.blacklisterror()

        if not args_page:
            args_page = 1
        else:
            args_page = int(args_page)
        if not args_kind:
            args_kind = 0
        else:
            args_kind = int(args_kind)
        # 在这一步执行判断,从reids中读取依据参数设定的key的value值,value值为pickle后的文件地址
        redis_key = str(args_kind) + "_" + str(args_page)
        file_path = get_pickle_file_path(redis_key)
        if file_path:
            # 如果能够获取到file_path,则直接反序列化path
            with open(file_path, "rb") as f:
                res_json = pickle.load(f)
                return res_json
        else:
            print("redis中没有缓存，执行从新查询操作")
            # 如果没有获取到file_path,则请求接口,把结果序列化进file_path中
            goods_list, total_num = get_all_kind_goods(args_page, args_kind)
            current_page = args_page
            max_page = math.ceil(int(total_num) / 100)
            res_json = {
                "code": 200,
                "message": "成功!",
                "data": {
                    "goods": goods_list,
                    "max_page": max_page,
                    "current_page": current_page
                }
            }
            # 判断目录是否存在
            if not os.path.exists(GOODS_INDEX_PATH):
                os.makedirs(GOODS_INDEX_PATH)
            # 进行序列化操作
            new_file_path = os.path.join(GOODS_INDEX_PATH, redis_key)
            with open(new_file_path, 'wb') as f:
                pickle.dump(res_json, f)
            # 把序列化后的文件路径存入redis中
            set_pickle_file_path(redis_key, new_file_path)
            return res_json

    def put(self):
        ts = time.time()
        args = self.parser.parse_args()
        args_page = args.get('page')
        args_words = args.get('words')
        args_order = args.get('order')
        time_stamp = args.get("timestamp")
        hash_string = args.get("hash_string")
        res = self.check_hash(time_stamp, hash_string)
        if not res:
            return self.hasherror()
        if args_words in mingan_words:
            return {
                "code": 410,
                "message": "敏感词汇",
                "data": ""
            }
        # 验证ip黑名单
        ip_addr = request.headers.get('X-Real-Ip')
        is_black_ip = self.check_black_ip()
        if is_black_ip:
            return self.blacklisterror()

        # 把搜索关键词存入数据库中
        save_one_searchwords(args_words, ip_addr)

        if not args_page:
            args_page = 1
        else:
            args_page = int(args_page)
        if not args_order:
            args_order = 0
        else:
            args_order = int(args_order)
        goods_list, total_num = util_search_goods(page=args_page, words=args_words, order=args_order)
        current_page = args_page
        max_page = math.ceil(int(total_num) / 100)
        res_json = {
            "code": 200,
            "message": "成功!",
            "data": {
                "goods": goods_list,
                "max_page": max_page,
                "current_page": current_page
            }
        }
        te = time.time()
        print("搜索商品花费了", str(te - ts))
        return res_json


class Detail(My_resource):
    def __init__(self):
        self.parser = reqparse.RequestParser()
        self.parser.add_argument("goods_id")
        self.parser.add_argument("timestamp")
        self.parser.add_argument("hash_string")
        self.parser.add_argument("coupon_id")
        self.parser.add_argument("goods_short_title")

    def get(self):
        args = self.parser.parse_args()
        goods_id = args.get('goods_id')
        time_stamp = args.get("timestamp")
        hash_string = args.get("hash_string")
        coupon_id = args.get("coupon_id")
        goods_short_title = args.get("goods_short_title")
        res = self.check_hash(time_stamp, hash_string)
        if not res:
            return self.hasherror()
        # 验证ip黑名单
        ip_addr = request.headers.get('X-Real-Ip')
        is_black_ip = self.check_black_ip()
        if is_black_ip:
            return self.blacklisterror()
        # 获取优惠券
        yhq = util_get_yhq(goods_id, coupon_id, goods_short_title)
        # 把执行获取的操作发给微信
        text_str = goods_short_title + str(yhq)
        # pool.submit(send_msg_to_weixin, ip_addr, text_str)
        yhq_dict = {}
        if yhq:
            yhq_dict['taokouling'] = yhq.get('taokouling')
            yhq_dict['shortlink'] = yhq.get('shortlink')
        return {
            "code": 200,
            "message": "成功!",
            "data": {
                "yhq": yhq_dict
            }
        }


class Feedback_api(My_resource):
    def __init__(self):
        self.parser = reqparse.RequestParser()
        self.parser.add_argument("feedback")
        self.parser.add_argument("timestamp")
        self.parser.add_argument("hash_string")

    def post(self):
        args = self.parser.parse_args()
        time_stamp = args.get("timestamp")
        hash_string = args.get("hash_string")
        res = self.check_hash(time_stamp, hash_string)
        if not res:
            return self.hasherror()
        # 验证ip黑名单
        is_black_ip = self.check_black_ip()
        if is_black_ip:
            return self.blacklisterror()

        feedback_string = args.get('feedback')

        # 发送反馈信息到微信
        pool.submit(send_feedback_to_wexin, feedback_string)

        # 保存反馈信息到数据库
        fb = Feedback()
        fb.feedback = feedback_string
        fb.save_time = datetime.datetime.now()
        db.session.add(fb)
        db.session.commit()
        return {
            "code": 200,
            "message": "成功",
            "data": ""
        }


class Version_api(My_resource):
    def __init__(self):
        self.parser = reqparse.RequestParser()
        self.parser.add_argument("timestamp")
        self.parser.add_argument("hash_string")

    def get(self):
        args = self.parser.parse_args()
        time_stamp = args.get("timestamp")
        hash_string = args.get("hash_string")
        res = self.check_hash(time_stamp, hash_string)
        if not res:
            return self.hasherror()
        version_num = VERSION_NUM
        shop_api_url = SHOP_API_URL
        # 验证ip黑名单
        is_black_ip = self.check_black_ip()
        if is_black_ip:
            return self.blacklisterror()

        return {
            "code": 200,
            "message": "成功",
            "data": {
                "version": version_num,
                "url": shop_api_url
            }
        }


class GoodsSearch(My_resource):

    def __init__(self):
        self.parser = reqparse.RequestParser()
        self.parser.add_argument("page")
        self.parser.add_argument("kind")
        self.parser.add_argument('words')
        self.parser.add_argument('order')
        self.parser.add_argument("timestamp")
        self.parser.add_argument("hash_string")

    def get(self):
        ts = time.time()
        args = self.parser.parse_args()
        args_page = args.get('page')
        args_words = args.get('words')
        args_order = args.get('order')
        time_stamp = args.get("timestamp")
        hash_string = args.get("hash_string")
        # 验证ip黑名单
        is_black_ip = self.check_black_ip()
        if is_black_ip:
            return self.blacklisterror()
        # 验证秘钥
        res = self.check_hash(time_stamp, hash_string)
        if not res:
            return self.hasherror()

        if args_words in mingan_words:
            return {
                "code": 410,
                "message": "敏感词汇",
                "data": ""
            }
        current_app.logger.warning("以下是搜索传的参数：")
        current_app.logger.warning(args_words)
        # 把搜索关键词存入数据库中
        ip_addr = request.headers.get('X-Real-Ip')
        save_one_searchwords(args_words, ip_addr)

        if not args_page:
            args_page = 1
        else:
            args_page = int(args_page)
        if not args_order:
            args_order = 0
        else:
            args_order = int(args_order)
        goods_list, total_num = util_search_goods(page=args_page, words=args_words, order=args_order)
        current_page = args_page
        max_page = math.ceil(int(total_num) / 100)
        res_json = {
            "code": 200,
            "message": "成功!",
            "data": {
                "goods": goods_list,
                "max_page": max_page,
                "current_page": current_page
            }
        }
        te = time.time()
        print("搜索商品花费了", str(te - ts))
        return res_json


class RecommendGoods(My_resource):

    def __init__(self):
        self.parser = reqparse.RequestParser()
        self.parser.add_argument("timestamp")
        self.parser.add_argument("hash_string")

    def get(self):
        args = self.parser.parse_args()
        time_stamp = args.get("timestamp")
        hash_string = args.get("hash_string")
        # 验证ip黑名单
        is_black_ip = self.check_black_ip()
        if is_black_ip:
            return self.blacklisterror()

        # 添加验证条件
        res = self.check_hash(time_stamp, hash_string)
        if not res:
            return self.hasherror()

        goods_list, total_num = get_recommend_goods()
        return {
            "code": 200,
            "data": {"goods": goods_list},
            "message": "200 ok"
        }


class Login(My_resource):
    def __init__(self):
        self.parser = reqparse.RequestParser()
        self.parser.add_argument("timestamp")
        self.parser.add_argument("hash_string")
        self.parser.add_argument("phone")
        self.parser.add_argument("code")

    # 获取手机号验证码
    def get(self):
        try:
            args = self.parser.parse_args()
            time_stamp = args.get("timestamp")
            hash_string = args.get("hash_string")
            phone = args.get("phone")
            # 验证ip黑名单
            is_black_ip = self.check_black_ip()
            if is_black_ip:
                return self.blacklisterror()

            res = self.check_hash(time_stamp, hash_string)
            if not res:
                return self.hasherror()
            # 执行发送短信
            pool.submit(send_message, phone)
            return {
                "code": 200,
                "message": "200 ok",
                "data": ""
            }
        except:
            exception_detail = traceback.format_exc()
            self.logger.error(exception_detail)
            return self.error_return()

    # 验证登录
    def post(self):
        try:
            args = self.parser.parse_args()
            time_stamp = args.get("timestamp")
            hash_string = args.get("hash_string")
            phone = args.get("phone")
            code = args.get("code")

            # 验证ip黑名单
            is_black_ip = self.check_black_ip()
            if is_black_ip:
                return self.blacklisterror()
            # 验证秘钥
            res = self.check_hash(time_stamp, hash_string)
            if not res:
                return self.hasherror()

            # 验证手机号和手机验证码
            right_code = get_phone_code(phone)
            if right_code != code:
                return {
                    "code": 400,
                    "message": "验证码错误",
                    "data": ""
                }

            # 判断用户表是否存在该用户，如果不存在则存入用户表
            one_user = get_user_by_phone(phone)
            user = User()
            if not one_user:
                user.phone = phone
                user.name = phone
                user.create_time = datetime.datetime.now()
                db.session.add(user)
                db.session.commit()
                user_id = user.id
            else:
                user_id = one_user.id

            # 生成一个token,然后保存到redis中，并把该token返回给前端
            token = get_md5_str(str(user_id) + str(time.time()))
            save_user_token(user_id, token)
            return {
                "code": 200,
                "data": token,
                "message": "200 ok"
            }
        except:
            exception_detail = traceback.format_exc()
            self.logger.error(exception_detail)
            return self.error_return()


class Browse(My_resource):
    '''
    浏览记录操作类
    '''

    def get(self):
        '''
        获取浏览记录
        :return:
        '''
        # 获取参数
        try:
            page, page_size = self.get_params(1, 'page', 'page_size')
            # 　验证token
            user_id = self.check_token()
            # 设置默认值
            if not page:
                page = 1
            if not page_size:
                page_size = 10
        except Exception as e:
            return self.error_dict.get(str(e))

        # 执行操作
        try:
            bh = BrowseHandler(user_id)
            # 执行保存用户浏览记录的操作
            data = bh.get_browse(page, page_size)
        except Exception as e:
            exception_detail = traceback.format_exc()
            self.logger.error(exception_detail)
            return self.error_return()
        return self.success_return(data)

    def post(self):
        '''
        保存浏览记录
        :return:
        '''
        # 获取参数
        try:
            goods_info = self.get_params(1, 'goods')
            # 　验证token
            user_id = self.check_token()
        except Exception as e:
            return self.error_dict.get(str(e))

        # 执行操作
        try:
            bh = BrowseHandler(user_id, goods_info)
            # 执行保存用户浏览记录的操作
            bh.save_browse()
        except Exception as e:
            exception_detail = traceback.format_exc()
            self.logger.error(exception_detail)
            return self.error_return()
        return self.success_return()


class RushBug(My_resource):
    def get(self):
        """
        获取抢购的商品信息
        :return:
        """
        # 获取参数
        try:
            page, page_size, item_type, start_time, end_time = self.get_params(1, 'page', 'page_size', "item_type",
                                                                               "start_time", "end_time", page=1,
                                                                               page_size=20)
        except Exception as e:
            return self.error_dict.get(str(e))

        # 执行操作
        try:
            params = {
                "page": page,
                "pagesize": page_size,
                "itemtype": item_type,
                "start_time": start_time,
                "end_time": end_time
            }
            rbh = RushBugHandler(taoqianggou_params=params, page=page, item_type=item_type, page_size=page_size)
            data = rbh.get_res()
        except Exception as e:
            exception_detail = traceback.format_exc()
            self.logger.error(exception_detail)
            return self.error_return()
        return self.success_return(data)
